package net.prasenjit.test.webmvc.controller;

import net.prasenjit.test.core.service.TestService;
import net.prasenjit.test.webmvc.model.Organization;
import net.prasenjit.test.webmvc.model.Person;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.MessageSource;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.*;

@Controller
@RequestMapping("/home")
public class HomeController {

    private static final Logger LOGGER = LogManager.getLogger(HomeController.class);
    @Autowired(required = false)
    @Qualifier("validator")
    private Validator validator;
    @Autowired
    private TestService testService;
    @Autowired
    private MongoOperations mongoOps;
    @Autowired
    private MessageSource messageSource;

    @RequestMapping
    public String index(Model model, Locale locale) {
        Organization o = new Organization();
        o.setName("jkhkj");
        Person p = new Person();
        o.setPerson(p);
        p.setName("sdsds");
        List<String> messages = new ArrayList<>();
        DefaultMessageCodesResolver codeResolver = new DefaultMessageCodesResolver();
        Set<ConstraintViolation<Organization>> violations = validator.validate(o);
        for (ConstraintViolation<Organization> constraintViolation : violations) {
            String messTemp = constraintViolation.getMessageTemplate();
            String[] codes = codeResolver.resolveMessageCodes(messTemp, "organization", constraintViolation.getPropertyPath()
                    .toString(), null);
            DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(codes,
                    constraintViolation.getMessage());
            String message = messageSource.getMessage(resolvable, locale);
            if (message.indexOf('{') < 0) {
                messages.add(message);
                continue;
            }
            Map<String, Object> attributes = constraintViolation.getConstraintDescriptor().getAttributes();
            StringBuilder builder = new StringBuilder();
            StringBuilder codeBuilder = new StringBuilder();
            boolean started = false;
            for (int i = 0; i < message.length(); i++) {
                char c = message.charAt(i);
                if (c == '{') {
                    started = true;
                } else if (c == '}' && started) {
                    started = false;
                    String code = codeBuilder.toString();
                    codeBuilder = new StringBuilder();
                    Object replacement = attributes.get(code);
                    if (replacement != null) {
                        builder.append(replacement.toString());
                    } else {
                        builder.append('{');
                        builder.append(code);
                        builder.append('}');
                    }
                } else if (started) {
                    codeBuilder.append(c);
                } else {
                    builder.append(c);
                }
            }
            if (started) {
                builder.append('{');
                builder.append(codeBuilder.toString());
            }

            messages.add(builder.toString());
        }
        model.addAttribute("violations", messages);
        return "index";
    }

    @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET)
    @ResponseBody
    public List<Organization> index1(@RequestParam(value = "start", required = false, defaultValue = "0") Integer start) {
        List<Organization> os = mongoOps.findAll(Organization.class);
        return os;
    }

    @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<Organization> indexPost(@RequestBody Organization o,
                                        @RequestParam(value = "start", required = false, defaultValue = "0") Integer start) {
        LOGGER.info("creating organization {}", o);
        mongoOps.insert(o);
        return index1(start);
    }

    @RequestMapping(value = "login", method = RequestMethod.GET)
    public String login(@RequestParam(value = "error", required = false) String error, Model model) {
        if (StringUtils.hasText(error)) {
            model.addAttribute("error", error);
        }
        return "login";
    }
}
